import java.util.ArrayList;
import java.util.List;

public class SearchNode
{
	private SearchNode parent;
	private SearchGrid grid;
	private int distSoFar;
	private int heuristic;
	private Move moveFromParent;

	public SearchNode(SearchGrid grid)
	{
		this(grid, null, -1, Move.WAIT);
	}

	public SearchNode(SearchGrid grid, SearchNode parent, int parentDistSoFar, Move moveFromParent)
	{
		this.grid = grid;
		this.parent = parent;
		distSoFar = parentDistSoFar + 1;
		this.moveFromParent = moveFromParent;
	}

	public void calculateHeuristic(Location goal)
	{
		Location loc = grid.getRobo();
		heuristic = Math.abs(goal.getX() - loc.getX()) + Math.abs(goal.getY() - loc.getY());
	}

	public int f()
	{
		return distSoFar + heuristic;
	}

	public int getHeuristic()
	{
		return heuristic;
	}

	public List<SearchNode> getNeighbors()
	{ // check for aliveness in BestFirst
		List<SearchNode> neighbors = new ArrayList<SearchNode>();

		SearchGrid neighbor = grid.update(Move.WAIT);
		if (neighbor != null)
			neighbors.add(new SearchNode(neighbor, this, distSoFar, Move.WAIT));

		neighbor = grid.update(Move.SHAVE);
		if (neighbor != null)
			neighbors.add(new SearchNode(neighbor, this, distSoFar, Move.SHAVE));

		neighbor = grid.update(Move.LEFT);
		if (neighbor != null)
			neighbors.add(new SearchNode(neighbor, this, distSoFar, Move.LEFT));

		neighbor = grid.update(Move.RIGHT);
		if (neighbor != null)
			neighbors.add(new SearchNode(neighbor, this, distSoFar, Move.RIGHT));

		neighbor = grid.update(Move.UP);
		if (neighbor != null)
			neighbors.add(new SearchNode(neighbor, this, distSoFar, Move.UP));

		neighbor = grid.update(Move.DOWN);
		if (neighbor != null)
			neighbors.add(new SearchNode(neighbor, this, distSoFar, Move.DOWN));
		return neighbors;
	}

	public int getDistSoFar()
	{
		return distSoFar;
	}

	public void setDistSoFar(int distSoFar)
	{
		this.distSoFar = distSoFar;
	}

	public String getPath()
	{
		SearchNode current = this;
		String directions = "";
		while (current != null)
		{
			directions = current.getMoveFromParent().toString().toUpperCase().charAt(0) + directions;
			current = current.getParent();
		}
		return directions.substring(1);
	}

	public void setGridNull()
	{
		grid = null;
	}

	public SearchNode getParent()
	{
		return parent;
	}

	public void setParent(SearchNode parent)
	{
		this.parent = parent;
	}

	public Move getMoveFromParent()
	{
		return moveFromParent;
	}

	public void setMoveFromParent(Move move)
	{
		moveFromParent = move;
	}

	public SearchGrid getGrid()
	{
		return grid;
	}

	@Override
	public String toString()
	{
		return grid.toString();
	}

	@Override
	public boolean equals(Object obj)
	{
		return obj.equals(grid);
	}

	@Override
	public int hashCode()
	{
		return grid.hashCode();
	}

}
